package com.iyouqu.dsp.api.server;

import java.io.IOException;
import java.lang.reflect.Field;
import java.net.InetSocketAddress;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.ext.Provider;

import org.jboss.resteasy.core.interception.PostMatchContainerRequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import io.netty.channel.ChannelHandlerContext;

@Component
@Provider
public class NettyFilter implements ContainerRequestFilter {
	public static final String HEADER_RESTEASY_CLIENT_IP = "X-Resteasy-Client-Ip";
	protected final Logger logger = LoggerFactory.getLogger(NettyFilter.class);

	// 获得请求的IP地址
	protected void getClientIP(PostMatchContainerRequestContext requestContext) {
		String ip = null;
		// 互联网访问
		String s1 = requestContext.getHeaderString("X-Real-IP");
		if (s1 == null) {
			// 互联网有代理访问
			s1 = requestContext.getHeaderString("X-Forwarded-For");
			if (s1 == null) {
				// 取socket 层 IP
				ip = getSocketRemoteAddrIp(requestContext);
			} else {
				ip = s1;
			}
		} else {
			ip = s1;
		}
		if (StringUtils.isEmpty(ip)) {
			ip = "0.0.0.0"; // 无法得到ip 时返回 0.0.0.0
		}
		// System.out.println(HEAD_NAME_RESTEASY_IP + " : " + ip);
		requestContext.getHeaders().putSingle(HEADER_RESTEASY_CLIENT_IP, ip);
	}

	private String getSocketRemoteAddrIp(PostMatchContainerRequestContext requestContext) {
		try {
			Field privateStringField = requestContext.getHttpRequest().getClass().getDeclaredField("ctx");
			privateStringField.setAccessible(true);
			ChannelHandlerContext ctx = (ChannelHandlerContext) privateStringField.get(requestContext.getHttpRequest());
			// System.out.println("ctx:\n" + ctx);
			// System.out.println("ctx.channel():\n" + ctx.channel());
			if (ctx != null && ctx.channel() != null && ctx.channel().remoteAddress() != null) {
				// System.out.println("ctx.channel().remoteAddress():\n" +
				// ctx.channel().remoteAddress());
				InetSocketAddress isAddr = (InetSocketAddress) ctx.channel().remoteAddress();
				if (isAddr.getAddress() != null) {
					// System.out.println("isAddr.getAddress():\n" +
					// isAddr.getAddress());
					return isAddr.getAddress().getHostAddress();
				}
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public void filter(ContainerRequestContext requestContext) throws IOException {
		PostMatchContainerRequestContext ctx = (PostMatchContainerRequestContext) requestContext;
		getClientIP(ctx);
	}
}
